package dk.liljedahl.christian.apx.shipdaemon;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.prefs.Preferences;

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.wb.swt.layout.grouplayout.GroupLayout;
import org.eclipse.wb.swt.layout.grouplayout.LayoutStyle;
import org.eclipse.wb.swt.SWTResourceManager;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Spinner;
import org.jivesoftware.smack.XMPPConnection;

import dk.liljedahl.christian.apx.ArduinoFirmata;
import dk.liljedahl.christian.apx.DummyPApplet;
import dk.liljedahl.christian.apx.XMPPMachine;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;

import cc.arduino.Arduino;

public class ShipDaemonWindow {

	static XMPPMachine xmppmachine; 
	static ArduinoFirmata arduino;
	static DummyPApplet dummyPApplet;

	static Mediator mediator;
	static XMPPConnection connection;	
	static CheckArduinoParameters checkArduinoParameters;

	protected Display display;
	protected Shell shlShipDaemon;
	private Text txtUsername;
	private Text txtPassword;
	private Text txtEventscript;
	private Text textResponseScript;
	private CLabel lblEventscriptfilename;
	private CLabel lblRFilename;
	private Button btnLoginToGtalk;
	private Combo comboSerial;
	private Spinner spinnerScriptPeriode;
	private Button btnRunEventScript;
	private Button btnStopEventScript;
	private Button buttonStartListening;
	private Button buttonStopListening;
	private Button btnConnectToArduino;
	private Text txtMessages;


	/**
	 * Launch the application.
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			ShipDaemonWindow window = new ShipDaemonWindow();
			window.open();
		} catch (Exception e) {			
			e.printStackTrace();
		}
	}

	/**
	 * Open the window.
	 */
	public void open() {
		display = Display.getDefault();
		

		// Make the stuff we need like Arduino
        // turn on the enhanced debugger
        XMPPConnection.DEBUG_ENABLED = true;
    	mediator = new Mediator();

    	xmppmachine = new XMPPMachine(mediator);
    	xmppmachine.listen = false; // We want to click the button before we start to listen.
    	dummyPApplet = new DummyPApplet();
    	
    	checkArduinoParameters = new CheckArduinoParameters(mediator);
    	
    	mediator.xmppmachine = xmppmachine;
    	mediator.responseScript = "";
    	mediator.eventScript = "";
	

		createContents();
		applyStartupPreferences();
		
		shlShipDaemon.open();
//		getPortsTask(getComboSerial()).start();
		//fillPortCombo(); // FIll the comboSerial - TODO - we might not want this, because it is so fucking slow

		shlShipDaemon.layout();
		while (!shlShipDaemon.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
		// End the firmata serial-fuck - and kill the processing-dummy?
		if(arduino != null){
			arduino.dispose();
		}

		// End the xmpp connection
		if(connection != null && connection.isConnected()){connection.disconnect();} 

	}

	private void applyStartupPreferences() {
		// Set username
		getTxtUsername().setText(mediator.prefs.get("GoogleTalkUsername", "username@gmail.com"));
		// Get the "name" of the port (would be "COM28" on windows from the preferences
		// Loop through the list in the combo and select whoever has that.
		// Or maybe we should actually do this where we fill the combo "Get Ports" !

		// Set Event Script filname label
		String eventScriptFilename = mediator.prefs.get("eventScriptFilename", "<no file>"); 
		getLblEventscriptfilename().setText(eventScriptFilename);
		if(!eventScriptFilename.equals("<no file>")){
			// Load Event Script from filename if a file exists
			FileMachine fm = new FileMachine();
			mediator.eventScript = fm.GetScriptText(eventScriptFilename);
			txtEventscript.setText(mediator.eventScript);
		}		
		// Set Response Script filname label
		String responseScriptFilename = mediator.prefs.get("responseScriptFilename", "<no file>"); 
		getLblRFilename().setText(responseScriptFilename);
		if(!responseScriptFilename.equals("<no file>")){
			// Load Response Script from filename if a file exists
			FileMachine fm = new FileMachine();
			mediator.responseScript = fm.GetScriptText(responseScriptFilename);
			textResponseScript.setText(mediator.responseScript);
		}		
		//  Set timerArduino-time
		int timerArdunoTime = (int) mediator.prefs.getLong("timeArduinoTime", 1000);
		spinnerScriptPeriode.setSelection(timerArdunoTime);
				
	}

	/**
	 * Create contents of the window.
	 */
	protected void createContents() {
		shlShipDaemon = new Shell();
		shlShipDaemon.setSize(630, 470);
		shlShipDaemon.setText("Ship Daemon");
		shlShipDaemon.setLayout(new FormLayout());

    	final Runnable timerArduino = new Runnable() {
    	      public void run() {
    	        	checkArduinoParameters.checkParameters(mediator.eventScript);
    	        	int period = Integer.parseInt(getSpinnerScriptPeriode().getText());
    	        	display.timerExec(period, this);
    	      }
    	    };

    	    FocusListener focusListener = new FocusListener() {
    	        public void focusGained(FocusEvent e) {
    	          Text t = (Text) e.widget;
    	          t.selectAll();
    	        }

    	        public void focusLost(FocusEvent e) {
    	          Text t = (Text) e.widget;
    	          if (t.getSelectionCount() > 0) {
    	            t.clearSelection();
    	          }
    	        }
    	      };
		Group grpGoogleTalk = new Group(shlShipDaemon, SWT.NONE);
		FormData fd_grpGoogleTalk = new FormData();
		fd_grpGoogleTalk.right = new FormAttachment(0, 316);
		fd_grpGoogleTalk.top = new FormAttachment(0, 5);
		fd_grpGoogleTalk.left = new FormAttachment(0, 5);
		grpGoogleTalk.setLayoutData(fd_grpGoogleTalk);
		grpGoogleTalk.setText("Google Talk");
		
		Group grpArduino = new Group(shlShipDaemon, SWT.NONE);
		FormData fd_grpArduino = new FormData();
		fd_grpArduino.right = new FormAttachment(100, -2);
		fd_grpArduino.left = new FormAttachment(grpGoogleTalk, 5);
		fd_grpArduino.top = new FormAttachment(0, 5);
		grpArduino.setLayoutData(fd_grpArduino);
		grpArduino.setText("Arduino");
		grpGoogleTalk.setLayout(new FormLayout());
		
		Composite composite_UsernamePassword = new Composite(grpGoogleTalk, SWT.NONE);
		FormData fd_composite_UsernamePassword = new FormData();
		fd_composite_UsernamePassword.top = new FormAttachment(0, 2);
		fd_composite_UsernamePassword.left = new FormAttachment(0);
		composite_UsernamePassword.setLayoutData(fd_composite_UsernamePassword);
		RowLayout rl_composite_UsernamePassword = new RowLayout(SWT.HORIZONTAL);
		rl_composite_UsernamePassword.marginTop = 0;
		rl_composite_UsernamePassword.marginRight = 0;
		rl_composite_UsernamePassword.marginLeft = 0;
		rl_composite_UsernamePassword.marginBottom = 0;
		composite_UsernamePassword.setLayout(rl_composite_UsernamePassword);
		
		Composite compositeUsername = new Composite(composite_UsernamePassword, SWT.NONE);
		RowLayout rl_compositeUsername = new RowLayout(SWT.HORIZONTAL);
		rl_compositeUsername.marginTop = 0;
		rl_compositeUsername.marginRight = 0;
		rl_compositeUsername.marginLeft = 0;
		rl_compositeUsername.marginBottom = 0;
		compositeUsername.setLayout(rl_compositeUsername);
		
		txtUsername = new Text(compositeUsername, SWT.BORDER);
		txtUsername.setLayoutData(new RowData(116, SWT.DEFAULT));
		txtUsername.setToolTipText("Username");
		txtUsername.setText("username");
		
		Composite composite_Password = new Composite(composite_UsernamePassword, SWT.NONE);
		RowLayout rl_composite_Password = new RowLayout(SWT.HORIZONTAL);
		rl_composite_Password.marginTop = 0;
		rl_composite_Password.marginRight = 0;
		rl_composite_Password.marginLeft = 0;
		rl_composite_Password.marginBottom = 0;
		composite_Password.setLayout(rl_composite_Password);
		
		txtPassword = new Text(composite_Password, SWT.BORDER);
		txtPassword.addFocusListener(focusListener);
		txtPassword.setToolTipText("Password");
		txtPassword.setText("password");
		txtPassword.addMouseListener(new MouseAdapter() {
		    public void mouseDown(final MouseEvent e) {
		        Text t = (Text) e.widget;
		        t.selectAll();
		      }
		    });
		
		Composite composite_GtalkButtons = new Composite(grpGoogleTalk, SWT.NONE);
		FormData fd_composite_GtalkButtons = new FormData();
		fd_composite_GtalkButtons.top = new FormAttachment(0, 34);
		fd_composite_GtalkButtons.left = new FormAttachment(0);
		composite_GtalkButtons.setLayoutData(fd_composite_GtalkButtons);
		composite_GtalkButtons.setLayout(new RowLayout(SWT.HORIZONTAL));
		
		btnLoginToGtalk = new Button(composite_GtalkButtons, SWT.NONE);
		btnLoginToGtalk.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				// We save the username to prefs at this time
				mediator.prefs.put("GoogleTalkUsername", txtUsername.getText()); // TODO - a clever way of storing the keys to avoid misspellings
				
				xmppmachine.set_LocalUsername(txtUsername.getText());
				xmppmachine.set_LocalPassword(txtPassword.getText());

				btnLoginToGtalk.setText("Opening connection..");
                connection = xmppmachine.openconnection();
                if(connection != null && connection.isConnected()){
    				btnLoginToGtalk.setText("Connected");
    				// clear password field
    				txtPassword.setText("********");
                }
			}
		});
		btnLoginToGtalk.setText("Connect to Google Talk");
		
		Button btnFriends = new Button(composite_GtalkButtons, SWT.NONE);
		btnFriends.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				// Lets make sure we have a connection before we do this TODO  - nullpointerexception-fuck
				if(connection != null && connection.isConnected()){
					String friends = xmppmachine.getAllFriendsS();
					final Shell dialog = new Shell(shlShipDaemon, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
					dialog.setSize(500, 400);
					dialog.setText("Friends");
			    	dialog.setLayout(new RowLayout());
			    	// Add Friend emailfield
					final Text textNewFriend = new Text(dialog, SWT.BORDER);
					textNewFriend.setLayoutData(new RowData(200, 20));
	
					// Add Friend button
					Button buttonAddFriend = new Button(dialog, SWT.PUSH); 
					Button buttonRemoveFriend = new Button(dialog, SWT.PUSH);
	
			    	final Text tRoster = new Text(dialog, SWT.MULTI | SWT.BORDER | SWT.WRAP | SWT.V_SCROLL | SWT.H_SCROLL);
	
					buttonAddFriend.setText("Add");
					buttonAddFriend.addSelectionListener(new SelectionAdapter(){
						public void widgetSelected(SelectionEvent e){
							String FriendEmail = textNewFriend.getText();
							xmppmachine.SendFriendRequest(FriendEmail);
							textNewFriend.setText(""); // Clear to indicate succes
							// Update list
							String newfriends = xmppmachine.getAllFriendsS();
							tRoster.setText(newfriends);
						}
					});
					buttonRemoveFriend.setText("Remove");
					buttonRemoveFriend.addSelectionListener(new SelectionAdapter(){
						public void widgetSelected(SelectionEvent e){
							String FriendEmail = textNewFriend.getText();
							xmppmachine.removeFriend(FriendEmail);
							textNewFriend.setText(""); // Clear to indicate succes
							// Update list
							String newfriends = xmppmachine.getAllFriendsS();
							tRoster.setText(newfriends);
						}
					});
	
	
					// Friend List
					tRoster.setLayoutData(new RowData(450, 300));
	
					tRoster.setText(friends);
				    dialog.open();			    
				}
			}
		});
		btnFriends.setText("Friends...");
		grpArduino.setLayout(new FormLayout());
		
		Composite composite = new Composite(grpArduino, SWT.NONE);
		FormData fd_composite = new FormData();
		fd_composite.top = new FormAttachment(0, 2);
		fd_composite.left = new FormAttachment(0, 3);
		composite.setLayoutData(fd_composite);
		composite.setLayout(new RowLayout(SWT.HORIZONTAL));
		
		CLabel lblSerialPort = new CLabel(composite, SWT.NONE);
		lblSerialPort.setText("Serial port");
		
		comboSerial = new Combo(composite, SWT.NONE);
		comboSerial.setLayoutData(new RowData(75, SWT.DEFAULT));
		comboSerial.setFont(SWTResourceManager.getFont("Tahoma", 8, SWT.NORMAL));

		//fillPortCombo(); // FIll the comboSerial - TODO - we might not want this, because it is so fucking slow

		Button btnGetPorts = new Button(composite, SWT.NONE);
		btnGetPorts.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				getPortsTask(getComboSerial()).start();
				//fillPortCombo();
			}
		});
		btnGetPorts.setText("Get ports");
		
		btnConnectToArduino = new Button(grpArduino, SWT.NONE);
		btnConnectToArduino.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				// TODO: We should only allow this, if we have serial port selected
				try {
					String portSelected = getComboSerial().getItem(getComboSerial().getSelectionIndex());
					arduino = new ArduinoFirmata(dummyPApplet, portSelected, 57600);
			    	mediator.arduinoFirmata = arduino;
			    	// Add to the preferences
			    	mediator.prefs.put("lastSerialUsed", portSelected);
			    	
			    	// Set the pinmodes after prefs
			    	setPinModesAfterPrefs();
			    	
			    	// Set button name to Connected
			    	getBtnConnectToArduino().setText("Connected");

				} catch (Exception e1) {
					getTxtMessages().setText(e1.getMessage());
				}
			}
		});
		FormData fd_btnConnectToArduino = new FormData();
		fd_btnConnectToArduino.top = new FormAttachment(composite, 6);
		fd_btnConnectToArduino.left = new FormAttachment(0);
		btnConnectToArduino.setLayoutData(fd_btnConnectToArduino);
		btnConnectToArduino.setText("Connect to Arduino");
		
		Button btnViewArduino = new Button(grpArduino, SWT.NONE);
		btnViewArduino.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				// code for opening Arduino viewer
				ArduinoDetails arduinoDetails = new ArduinoDetails(shlShipDaemon, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM, mediator);
				arduinoDetails.open();
			}
		});
		FormData fd_btnViewArduino = new FormData();
		fd_btnViewArduino.top = new FormAttachment(composite, 6);
		fd_btnViewArduino.right = new FormAttachment(100, -10);
		btnViewArduino.setLayoutData(fd_btnViewArduino);
		btnViewArduino.setText("View arduino");
		
		Group grpEventScript = new Group(shlShipDaemon, SWT.NONE);
		grpEventScript.setBackground(SWTResourceManager.getColor(176, 196, 222));
		FormData fd_grpEventScript = new FormData();
		fd_grpEventScript.right = new FormAttachment(grpArduino, 0, SWT.RIGHT);
		fd_grpEventScript.top = new FormAttachment(grpGoogleTalk, 6);
		fd_grpEventScript.bottom = new FormAttachment(0, 244);
		fd_grpEventScript.left = new FormAttachment(0, 5);
		grpEventScript.setLayoutData(fd_grpEventScript);
		grpEventScript.setText("Event Script - Monitor sensor events and send messages");
		grpEventScript.setLayout(new FormLayout());
		
		btnRunEventScript = new Button(grpEventScript, SWT.TOGGLE);
		btnRunEventScript.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				// We should only allow this, if xmpp and Arduino are running
				if(mediator.arduinoFirmata != null && connection !=null && connection.isConnected()){
					int timerArdunoTime = getSpinnerScriptPeriode().getSelection();

					display.timerExec(timerArdunoTime, timerArduino);
					
					// We save the value of the spinner to prefs for next openings of the program
					mediator.prefs.putLong("timeArduinoTime", timerArdunoTime);
					spinnerScriptPeriode.setSelection(timerArdunoTime);

					
					// Disable the Run button
					btnRunEventScript.setEnabled(false);
					// Pull out the Stop button
					btnStopEventScript.setSelection(false); // false = Out
					// Enable the Stop button
					btnStopEventScript.setEnabled(true);
				}
			}
		});
		FormData fd_btnRunEventScript = new FormData();
		fd_btnRunEventScript.left = new FormAttachment(0, 10);
		btnRunEventScript.setLayoutData(fd_btnRunEventScript);
		btnRunEventScript.setText("Run");
		
		btnStopEventScript = new Button(grpEventScript, SWT.TOGGLE);
		fd_btnRunEventScript.top = new FormAttachment(btnStopEventScript, 0, SWT.TOP);
		btnStopEventScript.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				display.timerExec(-1, timerArduino);
				// Disable the Stop button
				btnStopEventScript.setEnabled(false);
				// Pull out the Run button
				btnRunEventScript.setSelection(false); // false = Out
				// Enable the Run Button
				btnRunEventScript.setEnabled(true);

			}
		});
		FormData fd_btnStopEventScript = new FormData();
		fd_btnStopEventScript.top = new FormAttachment(0, 2);
		btnStopEventScript.setLayoutData(fd_btnStopEventScript);
		btnStopEventScript.setText("Stop");
		// And to start Stop should be in and disabled
		btnStopEventScript.setEnabled(false);
		btnStopEventScript.setSelection(true);

		
		txtEventscript = new Text(grpEventScript, SWT.BORDER | SWT.READ_ONLY | SWT.V_SCROLL | SWT.MULTI);
		txtEventscript.setBackground(SWTResourceManager.getColor(176, 196, 222));
		FormData fd_txtEventscript = new FormData();
		fd_txtEventscript.top = new FormAttachment(0, 32);
		fd_txtEventscript.left = new FormAttachment(0, 9);
		fd_txtEventscript.right = new FormAttachment(100, -9);
		txtEventscript.setLayoutData(fd_txtEventscript);
		
		Button btnEventOpenFile = new Button(grpEventScript, SWT.NONE);
		btnEventOpenFile.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				// Display the open file dialog
				FileDialog dialog = new FileDialog(shlShipDaemon, SWT.OPEN);
				//dialog.setFileName(filenameToLoad);
			    String filenameToLoad = dialog.open();
			    if(filenameToLoad != null){
				    getLblEventscriptfilename().setText(filenameToLoad);
				    FileMachine fm = new FileMachine();
				    String script = fm.GetScriptText(filenameToLoad);
				    txtEventscript.setText(script);
				    // And we need to set the mediator too
				    mediator.eventScript = script;
				    // And save to preferences, cause this is the file we want next time too
				    mediator.prefs.put("eventScriptFilename", filenameToLoad);
			    }
			}
		});
		FormData fd_btnEventOpenFile = new FormData();
		fd_btnEventOpenFile.top = new FormAttachment(0, 2);
		btnEventOpenFile.setLayoutData(fd_btnEventOpenFile);
		btnEventOpenFile.setText("Open file..");
		
		Button btnEventSaveAs = new Button(grpEventScript, SWT.NONE);
		btnEventSaveAs.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				FileDialog dialog = new FileDialog(shlShipDaemon, SWT.SAVE);
				String filenameToSave = getLblEventscriptfilename().getText();
				dialog.setFileName(filenameToSave);  // Get filename from filename-label
				filenameToSave = dialog.open();
				// Check for null to catch cancel
			    if(filenameToSave != null){
				    getLblEventscriptfilename().setText(filenameToSave); // Set the filename-label again, if the user changed the name
				    FileMachine fm = new FileMachine();
				    fm.SetScriptText(txtEventscript.getText(), filenameToSave); // We save the contents of the field, cause thats the most logical
				    // And save to preferences, cause this is the file we want next time too
				    mediator.prefs.put("eventScriptFilename", filenameToSave);
			    }
			}
		});
		fd_btnEventOpenFile.right = new FormAttachment(btnEventSaveAs, -6);
		FormData fd_btnEventSaveAs = new FormData();
		fd_btnEventSaveAs.top = new FormAttachment(0, 2);
		btnEventSaveAs.setLayoutData(fd_btnEventSaveAs);
		btnEventSaveAs.setText("Save as..");
		
		Button btnEventEdit = new Button(grpEventScript, SWT.NONE);
		fd_btnEventSaveAs.right = new FormAttachment(btnEventEdit, -6);
		btnEventEdit.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				// THis should make a new ScriptEditor
				final ScriptEditor scriptEditor = new ScriptEditor(shlShipDaemon, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM, mediator.eventScript, "Edit Event Script", "eventscript");
				String newscript = (String) scriptEditor.open(); 
				// No matter what, we can put the newscript back in the window
				txtEventscript.setText(newscript);
				// And put it into the mediator
				mediator.eventScript = newscript;
			}
		});
		FormData fd_btnEventEdit = new FormData();
		fd_btnEventEdit.top = new FormAttachment(0, 2);
		fd_btnEventEdit.right = new FormAttachment(100, -10);
		btnEventEdit.setLayoutData(fd_btnEventEdit);
		btnEventEdit.setText("Edit..");
		
		lblEventscriptfilename = new CLabel(grpEventScript, SWT.NONE);
		lblEventscriptfilename.setBackground(SWTResourceManager.getColor(176, 196, 222));
		fd_txtEventscript.bottom = new FormAttachment(100, -27);
		lblEventscriptfilename.setAlignment(SWT.RIGHT);
		lblEventscriptfilename.setFont(SWTResourceManager.getFont("Tahoma", 6, SWT.NORMAL));
		FormData fd_lblEventscriptfilename = new FormData();
		fd_lblEventscriptfilename.top = new FormAttachment(btnEventOpenFile, 71);
		fd_lblEventscriptfilename.left = new FormAttachment(0, 366);
		fd_lblEventscriptfilename.right = new FormAttachment(100, -15);
		lblEventscriptfilename.setLayoutData(fd_lblEventscriptfilename);
		lblEventscriptfilename.setText("filename");
		
		Group grpResponseScript = new Group(shlShipDaemon, SWT.NONE);
		grpResponseScript.setBackground(SWTResourceManager.getColor(240, 230, 140));
		grpResponseScript.setText("Response Script - Listen to incoming messages and respond");
		grpResponseScript.setLayout(new FormLayout());
		FormData fd_grpResponseScript = new FormData();
		fd_grpResponseScript.bottom = new FormAttachment(100, -53);
		fd_grpResponseScript.top = new FormAttachment(grpEventScript, 6);
		fd_grpResponseScript.left = new FormAttachment(grpGoogleTalk, 0, SWT.LEFT);
		fd_grpResponseScript.right = new FormAttachment(100);
		
		spinnerScriptPeriode = new Spinner(grpEventScript, SWT.BORDER);
		fd_btnStopEventScript.left = new FormAttachment(0, 258);
		spinnerScriptPeriode.setIncrement(100);
		spinnerScriptPeriode.setMaximum(100000);
		spinnerScriptPeriode.setSelection(1000);
		FormData fd_spinnerScriptPeriode = new FormData();
		fd_spinnerScriptPeriode.top = new FormAttachment(btnRunEventScript, 2, SWT.TOP);
		spinnerScriptPeriode.setLayoutData(fd_spinnerScriptPeriode);
		
		CLabel lblEvery = new CLabel(grpEventScript, SWT.NONE);
		fd_spinnerScriptPeriode.left = new FormAttachment(0, 149);
		lblEvery.setBackground(SWTResourceManager.getColor(176, 196, 222));
		lblEvery.setAlignment(SWT.RIGHT);
		FormData fd_lblEvery = new FormData();
		fd_lblEvery.bottom = new FormAttachment(btnRunEventScript, 0, SWT.BOTTOM);
		fd_lblEvery.right = new FormAttachment(spinnerScriptPeriode, -6);
		fd_lblEvery.top = new FormAttachment(0, 11);
		fd_lblEvery.left = new FormAttachment(0, 46);
		lblEvery.setLayoutData(fd_lblEvery);
		lblEvery.setText("every [ms] :");
		grpResponseScript.setLayoutData(fd_grpResponseScript);
		
		buttonStartListening = new Button(grpResponseScript, SWT.TOGGLE);
		buttonStartListening.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				xmppmachine.listen = true;
				// Disable the Run button
				buttonStartListening.setEnabled(false);
				// Pull out the Stop button
				buttonStopListening.setSelection(false); // false = Out
				// Enable the Stop button
				buttonStopListening.setEnabled(true);

			}
		});
		buttonStartListening.setText("Start listening");
		FormData fd_buttonStartListening = new FormData();
		fd_buttonStartListening.left = new FormAttachment(0, 10);
		buttonStartListening.setLayoutData(fd_buttonStartListening);
		
		buttonStopListening = new Button(grpResponseScript, SWT.TOGGLE);
		fd_buttonStartListening.top = new FormAttachment(buttonStopListening, 0, SWT.TOP);
		buttonStopListening.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				xmppmachine.listen = false;			
				// Disable the Stop button
				buttonStopListening.setEnabled(false);
				// Pull out the Start button
				buttonStartListening.setSelection(false); // false = Out
				// Enable the Start button
				buttonStartListening.setEnabled(true);
			}
		});
		buttonStopListening.setText("Stop");
		buttonStopListening.setEnabled(false);
		buttonStopListening.setSelection(true);
		
		FormData fd_buttonStopListening = new FormData();
		fd_buttonStopListening.top = new FormAttachment(0, 2);
		fd_buttonStopListening.left = new FormAttachment(buttonStartListening, 12);
		buttonStopListening.setLayoutData(fd_buttonStopListening);
		
		textResponseScript = new Text(grpResponseScript, SWT.BORDER | SWT.READ_ONLY | SWT.V_SCROLL | SWT.MULTI);
		textResponseScript.setBackground(SWTResourceManager.getColor(240, 230, 140));
		FormData fd_textResponseScript = new FormData();
		fd_textResponseScript.left = new FormAttachment(buttonStartListening, 0, SWT.LEFT);
		fd_textResponseScript.bottom = new FormAttachment(68);
		fd_textResponseScript.top = new FormAttachment(0, 31);
		textResponseScript.setLayoutData(fd_textResponseScript);
		
		Button buttonROpen = new Button(grpResponseScript, SWT.NONE);
		buttonROpen.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				// Display the open file dialog
				FileDialog dialog = new FileDialog(shlShipDaemon, SWT.OPEN);
				//dialog.setFileName(filenameToLoad);
			    String filenameToLoad = dialog.open();
			    // Check for null to catch cancel
			    if (filenameToLoad != null){
				    getLblRFilename().setText(filenameToLoad);
				    FileMachine fm = new FileMachine();
				    String script = fm.GetScriptText(filenameToLoad);
				    textResponseScript.setText(script);
				    // And we need to set the mediator too
				    mediator.responseScript = script;
				    // And save the filename to preferences 
				    mediator.prefs.put("responseScriptFilename", filenameToLoad);
			    }
			}
		});
		buttonROpen.setText("Open file..");
		FormData fd_buttonROpen = new FormData();
		fd_buttonROpen.top = new FormAttachment(0, 2);
		buttonROpen.setLayoutData(fd_buttonROpen);
		
		Button buttonRSave = new Button(grpResponseScript, SWT.NONE);
		buttonRSave.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				FileDialog dialog = new FileDialog(shlShipDaemon, SWT.SAVE);
				String filenameToSave = getLblRFilename().getText();
				dialog.setFileName(filenameToSave);  // Get filename from filename-label
				filenameToSave = dialog.open();	// Get the filename from the save-dialog return value
				// Check for null to catch cancel
			    if(filenameToSave != null){
				    getLblRFilename().setText(filenameToSave); // Set the filename-label again, if the user changed the name
				    FileMachine fm = new FileMachine();
				    fm.SetScriptText(textResponseScript.getText(), filenameToSave); // We save the contents of the field, cause thats the most logical
				    // And save the filename to preferences - 
				    mediator.prefs.put("responseScriptFilename", filenameToSave);

			    }
			}
		});
		fd_buttonROpen.right = new FormAttachment(buttonRSave, -6);
		buttonRSave.setText("Save as..");
		FormData fd_buttonRSave = new FormData();
		fd_buttonRSave.top = new FormAttachment(0, 2);
		buttonRSave.setLayoutData(fd_buttonRSave);
		
		Button buttonREdit = new Button(grpResponseScript, SWT.NONE);
		fd_textResponseScript.right = new FormAttachment(buttonREdit, 0, SWT.RIGHT);
		buttonREdit.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				// THis should make a new ScriptEditor
				final ScriptEditor scriptEditor = new ScriptEditor(shlShipDaemon, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM, mediator.responseScript, "Edit Response Script", "responsescript");
				String newscript = (String) scriptEditor.open(); 
				// No matter what, we can put the newscript back in the window
				textResponseScript.setText(newscript);
				// And we need to save it to the mediator too
				mediator.responseScript = newscript;
			}
		});
		fd_buttonRSave.right = new FormAttachment(buttonREdit, -6);
		buttonREdit.setText("Edit..");
		FormData fd_buttonREdit = new FormData();
		fd_buttonREdit.top = new FormAttachment(0, 2);
		fd_buttonREdit.right = new FormAttachment(100, -10);
		buttonREdit.setLayoutData(fd_buttonREdit);
		
		lblRFilename = new CLabel(grpResponseScript, SWT.NONE);
		lblRFilename.setBackground(SWTResourceManager.getColor(240, 230, 140));
		lblRFilename.setAlignment(SWT.RIGHT);
		lblRFilename.setFont(SWTResourceManager.getFont("Tahoma", 6, SWT.NORMAL));
		FormData fd_lblRFilename = new FormData();
		fd_lblRFilename.top = new FormAttachment(buttonROpen, 54);
		fd_lblRFilename.left = new FormAttachment(0, 365);
		fd_lblRFilename.right = new FormAttachment(100, -16);
		lblRFilename.setLayoutData(fd_lblRFilename);
		lblRFilename.setText("filename");
		
		txtMessages = new Text(shlShipDaemon, SWT.BORDER | SWT.READ_ONLY | SWT.V_SCROLL | SWT.MULTI);
		txtMessages.setText("Messages");
		FormData fd_txtMessages = new FormData();
		fd_txtMessages.bottom = new FormAttachment(grpResponseScript, 43, SWT.BOTTOM);
		fd_txtMessages.top = new FormAttachment(grpResponseScript, 6);
		fd_txtMessages.right = new FormAttachment(100, -2);
		fd_txtMessages.left = new FormAttachment(0, 5);
		txtMessages.setLayoutData(fd_txtMessages);

	}
	
	public Thread getPortsTask(Combo combo) {
	    final Combo portCombo = combo;
	    return new Thread() {

	      public void run() {
	        
	        display.asyncExec(new Runnable() {
	          public void run() {
	            
	      		String ports[];
				try {
					ports = Arduino.list();
		    		// Clean it
		    		getComboSerial().removeAll();
		    		// Add elements
		    		for (String p: ports)
		    	    {
		    			getComboSerial().add(p);
		    	    }
		    		String lastSerialUsed = mediator.prefs.get("lastSerialUsed", "");
		    		if(lastSerialUsed.equals("")){
		    			// Just pick the first in the list
		    			getComboSerial().select(0);			
		    		} else {
		    			// Pick the one matching the prefs
		    			getComboSerial().select(getComboSerial().indexOf(lastSerialUsed));
		    		}
				} catch (Exception e) {
					getTxtMessages().setText(getCustomStackTrace(e));
					
				}	            
	          }
	        });
	      }
	    };
	  }  
	private void fillPortCombo(){
	}
	
	private void setPinModesAfterPrefs(){
		// Set the actual pinmode
		for(int i = 0;i<14;i++){
			// We should loop the preferences here and set the buttons accordingly
			String savedPinmode = mediator.prefs.get("pinmode"+i, "IN");
			if(savedPinmode.equals("IN")){
				mediator.arduinoFirmata.pinMode(i, 0);  // 0: INPUT, 1:OUTPUT
			}
			if(savedPinmode.equals("OUT")){
				mediator.arduinoFirmata.pinMode(i, 1);  // 0: INPUT, 1:OUTPUT
				// Set the button look
			}

		}

	}
	
	public static String getStackTrace(Throwable aThrowable) {
	    final Writer result = new StringWriter();
	    final PrintWriter printWriter = new PrintWriter(result);
	    aThrowable.printStackTrace(printWriter);
	    return result.toString();
	  }
	
	public static String getCustomStackTrace(Throwable aThrowable) {
	    //add the class name and any message passed to constructor
	    final StringBuilder result = new StringBuilder( "BOO-BOO: " );
	    result.append(aThrowable.toString());
	    final String NEW_LINE = System.getProperty("line.separator");
	    result.append(NEW_LINE);

	    //add each element of the stack trace
	    for (StackTraceElement element : aThrowable.getStackTrace() ){
	      result.append( element );
	      result.append( NEW_LINE );
	    }
	    return result.toString();
	  }
	protected CLabel getLblEventscriptfilename() {
		return lblEventscriptfilename;
	}
	protected CLabel getLblRFilename() {
		return lblRFilename;
	}
	protected Button getBtnLoginToGtalk() {
		return btnLoginToGtalk;
	}
	protected Combo getComboSerial() {
		return comboSerial;
	}
	protected Spinner getSpinnerScriptPeriode() {
		return spinnerScriptPeriode;
	}
	protected Text getTxtUsername() {
		return txtUsername;
	}
	protected Button getBtnRunEventScript() {
		return btnRunEventScript;
	}
	protected Button getBtnStopEventScript() {
		return btnStopEventScript;
	}
	protected Button getButtonStartListening() {
		return buttonStartListening;
	}
	protected Button getButtonStopListening() {
		return buttonStopListening;
	}
	protected Button getBtnConnectToArduino() {
		return btnConnectToArduino;
	}
	protected Text getTxtMessages() {
		return txtMessages;
	}
}
